﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using HotUpdate.Config;
using UnityEngine;
using UnityEngine.UI;

namespace HotUpdate.GUI
{
    public class UIMgr
    {
        private static Dictionary<Type, UIWindowBase> _windowDic = new();
        private static Stack<UIWindowBase> _windowStack = new();
        private static Camera _uiCamera;
        public static Camera UICamera => _uiCamera;
        private static Canvas _uiCanvas;
        public static Canvas UICanvas => _uiCanvas;
        private static UIWindowBase _nowUIWindow;

        public static void Start()
        {
            _uiCamera = GameObject.Find("UICamera").GetComponent<Camera>();
            _uiCanvas = GameObject.Find("UICanvas").GetComponent<Canvas>();
            // InitRootCanvas();
        }

        public static T OpenWindow<T>(Transform parent = default, EWindowOpenType openType = EWindowOpenType.Normal)
            where T : UIWindowBase
        {
            if (parent == default)
            {
                parent = UICanvas.transform;
            }

            Type type = typeof(T);
            if (_windowDic.ContainsKey(type))
            {
                Debug.LogWarning("当前窗口已存在");
                return _windowDic[type] as T;
            }

            string name1 = type.Name;
            string name2 = "Window";
            string name = Regex.Replace(name1, name2, "");
            string path = ProjectCfg.UIRootPath + name + "/" + "Prefabs/" + type.Name + ".prefab";
            GameObject windowPrefab = GameMgr.ResMgr.LoadAsset<GameObject>(path);
            if (windowPrefab == null)
                throw new Exception("资源中不存在这个ui脚本请按照生成ui的流程进行创建ui");
            GameObject windowObj = GameObject.Instantiate(windowPrefab, parent);
            UIWindowBase window = windowObj.GetComponent<UIWindowBase>();
            if (window == null)
                throw new Exception("当前ui脚本没有挂载对应脚本");
            window.WindowType = type;
            window.SetVisible(true);
            _windowDic.Add(type, window);
            switch (openType)
            {
                case EWindowOpenType.Normal:
                    _windowStack.Push(window);
                    break;
                case EWindowOpenType.Replace:
                    if (_nowUIWindow != null)
                    {
                        CloseWindow(_nowUIWindow);
                        _nowUIWindow = null;
                    }

                    _nowUIWindow = window;
                    break;
            }

            window.OpenType = openType;
            window.OnEnter();
            return window as T;
        }

        public static bool CloseWindow<T>() where T : UIWindowBase
        {
            T window = GetWindow<T>();
            if (window == null)
                return false;
            CloseWindow(window);
            return true;
        }

        public static void RollbackWindow(int cnt = 1)
        {
            if (_windowStack.Count >= cnt)
            {
                while (cnt-- > 0)
                {
                    CloseWindow(_windowStack.Pop());
                }
            }
        }

        private static void CloseWindow(UIWindowBase window)
        {
            switch (window.OpenType)
            {
                case EWindowOpenType.Replace:
                    _nowUIWindow = null;
                    break;
            }

            Type key = null;
            foreach (var type in _windowDic.Keys)
            {
                var wd = _windowDic[type];
                if (wd == window)
                {
                    key = type;
                }
            }
            if (key != null)
            {
                _windowDic.Remove(key);
            }
            window.SetVisible(false);
            window.OnClose();
        }

        public static T GetWindow<T>() where T : UIWindowBase
        {
            Type type = typeof(T);
            if (_windowDic.TryGetValue(type, out UIWindowBase window))
                return window as T;
            return null;
        }

        public static void Update()
        {
            foreach (var window in _windowDic.Values)
            {
                window.OnUpdate();
            }
        }

        private static void InitRootCanvas()
        {
            var canvasScaler = _uiCanvas.GetComponent<CanvasScaler>();
            float designWidth = 1920;
            float designHeight = 1080;
            float designAspect = designWidth / designHeight;
            float whAspect = Screen.width / (float)Screen.height;
            float mathWidthOrHeight = 0;
            if (whAspect < designAspect)
            {
                mathWidthOrHeight = 1;
            }

            canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
            canvasScaler.matchWidthOrHeight = mathWidthOrHeight;
        }
    }
}